#include "lexer.hpp"
#include <cctype>
#include <string>
const std::unordered_set<std::string> KW = {
	// --- DML / DQL ---
	"SELECT", "INSERT", "UPDATE", "DELETE",
	"INTO", "VALUES", "FROM", "WHERE", "GROUP", "BY", "HAVING",
	"ORDER", "ASC", "DESC", "LIMIT", "OFFSET", "DISTINCT", "SET",

	// --- DDL ---
	"CREATE", "DROP", "ALTER", "TRUNCATE", "RENAME",
	"TABLE", "VIEW", "INDEX", "DATABASE", "SCHEMA", "COLUMN",
	"ADD", "MODIFY","CHANGE",

	// --- 约束 ---
	"PRIMARY", "KEY", "FOREIGN", "REFERENCES", "CHECK",
	"UNIQUE", "NOT", "NULL", "DEFAULT", "AUTO_INCREMENT",
	"CONSTRAINT", "COMMENT",

	// --- 逻辑 / 比较运算符 ---
	"AND", "OR", "NOT", "IN", "BETWEEN", "LIKE", "IS", "EXISTS",

	// --- 聚合函数 ---
	"COUNT", "SUM", "AVG", "MIN", "MAX",

	// --- SHOW / 管理类 ---
	"SHOW", "TABLES", "USE", "INDICES", "INDEXES",

	// --- 数据类型 ---
	"INT", "INTEGER", "SMALLINT", "BIGINT",
	"FLOAT", "DOUBLE", "DECIMAL", "NUMERIC",
	"CHAR", "VARCHAR", "TEXT", "BLOB",
	"DATE", "TIME", "DATETIME", "TIMESTAMP",
	"BOOLEAN", "BOOL", "JSON", "TINYINT", "UNSIGNED",

	// --- 其他常用 ---
	"TRUE", "FALSE", "AS", "ON", "JOIN", "INNER", "LEFT", "RIGHT", "FULL", "OUTER", "CROSS",
	"RAND"};

Lexer::Lexer(std::string src) : s(std::move(src)) {}
char Lexer::peek() { return i < (int)s.size() ? s[i] : 0; }
char Lexer::get()
{
	char c = peek();
	if (!c)
		return 0;
	i++;
	if (c == '\n')
	{
		line++;
		col = 1;
	}
	else
		col++;
	return c;
}
void Lexer::push(TokType t, std::string lex, int l, int c) { out.push_back({t, lex, l, c}); }
void Lexer::lexAll()
{
	while (true)
	{
		char c = peek();
		if (!c)
			break;

		if (isspace((unsigned char)c))
		{
			get();
			continue;
		}
		int l = line, c0 = col;

		if (isalpha((unsigned char)c) || c == '_')
		{
			std::string v;
			while (isalnum((unsigned char)peek()) || peek() == '_')
				v.push_back(get());

			std::string up = v;
			for (auto &ch : up)
				ch = toupper(ch);

			if (KW.count(up))
				push(TokType::KW, up, l, c0);
			else
				push(TokType::IDENT, v, l, c0);
		}
		else if (isdigit((unsigned char)c))
		{
			std::string v;
			bool hasDot = false;

			// 整数部分
			while (isdigit((unsigned char)peek()))
				v.push_back(get());

			// 如果有小数点，尝试解析小数部分
			if (peek() == '.')
			{
				hasDot = true;
				v.push_back(get()); // 吃掉 '.'

				while (isdigit((unsigned char)peek()))
					v.push_back(get());
			}

			// 科学计数法（可选）
			if (peek() == 'e' || peek() == 'E')
			{
				hasDot = true;
				v.push_back(get()); // 吃掉 e/E
				if (peek() == '+' || peek() == '-')
					v.push_back(get()); // 吃掉符号
				while (isdigit((unsigned char)peek()))
					v.push_back(get());
			}

			if (hasDot)
				push(TokType::FLOATLIT, v, l, c0);
			else
				push(TokType::INTLIT, v, l, c0);
		}

		else if (c == '\'')
		{ // string literal
			get();
			std::string v;
			while (true)
			{
				char p = peek();
				if (!p)
				{
					push(TokType::ERR, "Unclosed string", l, c0);
					return;
				}
				get();
				if (p == '\'')
				{
					break;
				}
				if (p == '\\')
				{
					char n = peek();
					if (n)
					{
						v.push_back(get());
					}
				}
				else
					v.push_back(p);
			}
			push(TokType::STRLIT, v, l, c0);
		}
		else
		{
			char next_char = s[i + 1]; // 安全向前看（因为 peek() 保证了 i < size）

			if (c == '-' && isdigit((unsigned char)next_char))
			{
				// 这是负数的一部分，而不是减法操作符
				std::string v;
				v.push_back(get()); // 先吃掉负号 '-'

				bool hasDot = false;
				while (isdigit((unsigned char)peek()))
					v.push_back(get());

				if (peek() == '.')
				{
					hasDot = true;
					v.push_back(get());
					while (isdigit((unsigned char)peek()))
						v.push_back(get());
				}

				// 科学计数法 (可选)
				if (peek() == 'e' || peek() == 'E')
				{
					hasDot = true;
					v.push_back(get());
					if (peek() == '+' || peek() == '-')
						v.push_back(get());
					while (isdigit((unsigned char)peek()))
						v.push_back(get());
				}

				if (hasDot)
					push(TokType::FLOATLIT, v, l, c0);
				else
					push(TokType::INTLIT, v, l, c0);
			}
			else
			{
				// 处理单字符和多字符操作符
				std::string op(1, get());

				if (op == "<" || op == ">" || op == "!" || op == "=")
				{
					if (peek() == '=')
					{
						op.push_back(get()); // 组合成 <=, >=, !=, ==
					}
					else if (op == "<" && peek() == '>')
					{
						op.push_back(get()); // 组合成 <>
					}
				}

				if (op == "(" || op == ")" || op == "," || op == ";")
					push(TokType::DELIM, op, l, c0);
				else if (op == "<" || op == ">" || op == "=" || op == "*" || op == "-" || op == "+" || op == "/" ||
						 op == "!=" || op == "<>" || op == ">=" || op == "<=")
					push(TokType::OP, op, l, c0);
				else
					push(TokType::ERR, std::string("Unexpected char ") + op, l, c0);
			}
		}
	}
	push(TokType::END, "<eof>", line, col);
}